﻿// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;

namespace Seagull.Extensions.ServiceBus
{
    /// <summary>
    /// Default implement of <see cref="T:DotNetCore.CAP.Internal.IBootstrapper" />.
    /// </summary>
    internal class HostedService : BackgroundService
    {
        private readonly ILogger<HostedService> _logger;
        private readonly DelayOptions _options;
        private readonly DotNetCore.CAP.RabbitMQOptions _capOptions;
        private readonly DotNetCore.CAP.RabbitMQ.IConnectionChannelPool _connectionChannelPool;
        public HostedService(DotNetCore.CAP.RabbitMQ.IConnectionChannelPool connectionChannelPool,
            IOptions<DelayOptions> options,
            IOptions<DotNetCore.CAP.RabbitMQOptions> optionsAccessor,
            ILogger<HostedService> logger)
        {
            _connectionChannelPool = connectionChannelPool;
            _options = options.Value;
            _capOptions = optionsAccessor.Value;
            _logger = logger;
        }

        public async Task BootstrapAsync()
        {
            _logger.LogDebug("### Bus background task is starting.");

            await BootstrapCoreAsync();

            _logger.LogInformation("### Bus started!");
        }

        protected virtual Task BootstrapCoreAsync()
        {
            if (_options is null)
                return Task.CompletedTask;
            var _connection = _connectionChannelPool.GetConnection();

            var _channel = _connection.CreateModel();
            Dictionary<string, object> argMaps = _options.ExchangeArguments;
            if (_options.ExchangeArguments is null)
            {
                argMaps = new Dictionary<string, object>() { { "x-delayed-type", _options.ExchangeType } };
            }
            else
            {
                argMaps.Add("x-delayed-type", _options.ExchangeType);
            }
            _channel.ExchangeDeclare(_capOptions.ExchangeName, DotNetCore.CAP.RabbitMQOptions.ExchangeType, true);
            _channel.ExchangeDeclare(_options.ExchangeName, "x-delayed-message", true, false, argMaps);
            _channel.ExchangeBind(_capOptions.ExchangeName, _options.ExchangeName, "");
            return Task.CompletedTask;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await BootstrapAsync();
        }

        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            await base.StopAsync(cancellationToken);
        }
    }
}